from fastapi import APIRouter, Depends, HTTPException, Query, Request, status, Body
from sqlalchemy.orm import Session
from datetime import timedelta

from app.database.database import get_db
from app.database.repository.user_repository import UserRepository
from app.exception.code_exception import CodeException
from app.schemas.rr import RR
from app.schemas.user import UserDTO
from app.utils.crypto import AESCrypto
from app.utils.jwt_utils import JWTUtils
from app.utils.request_utils import RequestUtils

router = APIRouter(tags=["login"])

@router.post("/login", response_model=RR[dict])
async def login(
    # 对于 GET 请求使用 Query 参数，对于 POST 请求使用 Body 参数
    username: str = Body(..., min_length=1, description="用户名"),
    pwd: str = Body(..., min_length=1, description="密码"),
    db: Session = Depends(get_db)
):
    """
    用户登录
    
    Args:
        username: 用户名
        pwd: 密码
        db: 数据库会话
        
    Returns:
        RR[dict]: 包含用户信息和token的响应
    """
    # 查找用户
    user_repo = UserRepository(db)
    user = user_repo.find_by_name(username)
    
    if not user:
        raise CodeException.sys_error("用户名或密码错误")
    
    # 验证密码
    try:
        decrypted_pwd = AESCrypto.decrypt(user.pwd)
        if decrypted_pwd != pwd:
            raise CodeException.sys_error("用户名或密码错误")
    except Exception:
        raise CodeException.sys_error("用户名或密码错误")
    
    # 创建访问令牌
    access_token = JWTUtils.create_access_token(data={"sub": str(user.id)}, expires_delta=timedelta(days=30))
    
    # 构建响应
    return RR.success({
        "user": UserDTO.model_validate(user).model_dump(),
        "token": access_token
    })

@router.post("/logout", response_model=RR[dict])
async def logout(request: Request, db: Session = Depends(get_db)):
    user = RequestUtils.login_user_and_check(request, db)
    token = RequestUtils.get_token(request)
    """
    用户登出
    
    Returns:
        RR[dict]: 登出成功响应
    """
    # 在实际应用中，可能需要将token加入黑名单或执行其他清理操作
    # 这里简单返回成功状态
    return RR.success({token: token, user: UserDTO.model_validate(user).model_dump()})
